# pragma once

# include "cpp_tools_Headers.h"


namespace cpp_tools
{
    // 黄金分割
    std::tuple<double, double, int> goldenSection(std::function<double(double)> fun_f, double a, double b, 
        double val_max_error, double s_max_error, int iter_max) 
    {
        const double t = (std::sqrt(5) - 1) / 2;
        double h = b - a;

        double val_a = fun_f(a);
        double val_b = fun_f(b);

        double p = a + (1 - t) * h;
        double q = a + t * h;

        double val_p = fun_f(p);
        double val_q = fun_f(q);

        int iter = 0;
        while (std::abs(val_a - val_b) >= val_max_error || std::abs(h) > s_max_error) {
            if (val_p <= val_q) {
                b = q;
                val_b = val_q;

                q = p;
                val_q = val_p;

                h = b - a;
                p = a + (1 - t) * h;
                val_p = fun_f(p);
            } else {
                a = p;
                val_a = val_p;

                p = q;
                val_p = val_q;

                h = b - a;
                q = a + t * h;
                val_q = fun_f(q);
            }

            iter++;
            if (iter >= iter_max) {
                break;
            }
        }

        double s, val;
        if (val_p <= val_q) {
            s = p;
            val = val_p;
        } else {
            s = q;
            val = val_q;
        }

        return {s, val, iter};
    }
} // namespace cpp_tools

